<?php
/**
 * Created by PhpStorm.
 * User: worry
 * Date: 2017/9/11
 * Time: 17:31
 */

namespace controllers;


use lib\Model;
use lib\Snoopy;

class Lottery
{
    private $Snoopy;
    public function __construct()
    {
        $this->Snoopy = new Snoopy();
    }




    /**
     * 大乐透
     */
    public function getSuperLottery()
    {
        //历史记录 URL
        $url = "http://www.lottery.gov.cn/historykj/history.jspx?_ltype=dlt";
        $result = $this->getUrlResult($url);

        //获取总页数
        preg_match_all('/<div\s*?class="page">.*?<div>.*?<select.*?>.*?(<option.*?>\d+<\/option>)+.*?<\/select>.*?<\/div>.*?<\/div>/is', $result, $matches);
        preg_match_all('/option.*?>(\d+)<\/option/', $matches[0][0], $pages);
        $totalPage = array_pop($pages[1]);
        if(!is_numeric($totalPage)) {
            throw new \Exception('获取总页数失败');
        }

        //表结构语句
        $createTableSql = " CREATE TABLE IF NOT EXISTS `super_lottery` (
              `issue` int(10) unsigned NOT NULL COMMENT '期号',
              `red_1` tinyint(3) unsigned NOT NULL COMMENT '红球1',
              `red_2` tinyint(3) unsigned NOT NULL COMMENT '红球2',
              `red_3` tinyint(3) unsigned NOT NULL COMMENT '红球3',
              `red_4` tinyint(3) unsigned NOT NULL COMMENT '红球4',
              `red_5` tinyint(3) unsigned NOT NULL COMMENT '红球5',
              `blue_1` tinyint(3) unsigned NOT NULL COMMENT '蓝球1',
              `blue_2` tinyint(3) unsigned NOT NULL COMMENT '蓝球2',
              `first_num` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '一等奖注数',
              `first_money` varchar(20) NOT NULL DEFAULT '' COMMENT '一等奖资金',
              `first_append_num` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '一等奖追加注数',
              `first_append_money` varchar(20) NOT NULL DEFAULT '' COMMENT '一等奖追加资金',
              `second_num` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '二等奖注数',
              `second_money` varchar(20) NOT NULL DEFAULT '' COMMENT '二等奖资金',
              `second_append_num` smallint(5) unsigned NOT NULL DEFAULT '0' COMMENT '二等奖追加注数',
              `second_append_money` varchar(20) NOT NULL DEFAULT '' COMMENT '二等奖追加资金',
              `sale_total` varchar(20) NOT NULL DEFAULT '' COMMENT '销售额',
              `bonus_total` varchar(20) NOT NULL DEFAULT '' COMMENT '奖池',
              `date` date NOT NULL COMMENT '开奖日期',
              PRIMARY KEY (`issue`)
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='大乐透'";
        $model = new Model(\lib\App::$config['db_lottery']);
        $model->exec($createTableSql);
        $model->table('super_lottery');

        //逐页获取数据
        for($p = 1; $p <= $totalPage; $p++) {
            $pageUrl = $p == 1 ? $url : str_replace('history.jspx', 'history_'.$p.'.jspx', $url);
            $result = $this->getSuperLotteryTableData($pageUrl);
            foreach($result as $item) {
                //已经存在的数据跳过
                if($model->find($item['issue'])) {
                    continue;
                }
                if(!$model->add($item)) {
                    throw new \Exception('添加数据异常:'.json_encode($item));
                }
            }
        }
        return 0;
    }

    /**
     * 获取内容
     * @param $url
     * @return mixed
     */
    public function getUrlResult($url)
    {
        $this->Snoopy->fetch($url);
        $result = $this->Snoopy->getResults();
        return $result;
    }

    /**
     * 获取双色球数据
     * @return int
     * @throws \Exception
     * @internal param $url
     */
    public function getDoubleLottery()
    {
        $url = 'http://kaijiang.zhcw.com/zhcw/html/ssq/list.html';
        //获取总页数
        $result = $this->getUrlResult($url);
        preg_match('/<p\s*?class="pg">.*?(\d+).*?\/.*?\d+\s*<\/strong>/', $result, $pageMatches);
        if(!is_numeric($pageMatches[1])) {
            throw new \Exception('获取总页数失败');
        }
        $totalPage = $pageMatches[1];

        //表结构语句
        $createTableSql = " CREATE TABLE IF NOT EXISTS `double_lottery` (
              `issue` int(10) unsigned NOT NULL COMMENT '基数',
              `front_1` tinyint(4) NOT NULL COMMENT '前区1',
              `front_2` tinyint(4) NOT NULL COMMENT '前区2',
              `front_3` tinyint(4) NOT NULL COMMENT '前区3',
              `front_4` tinyint(4) NOT NULL COMMENT '前区4',
              `front_5` tinyint(4) NOT NULL COMMENT '前区5',
              `front_6` tinyint(4) NOT NULL COMMENT '前区6',
              `back` tinyint(4) NOT NULL COMMENT '后区',
              `date` date NOT NULL COMMENT '开奖日期',
              PRIMARY KEY (`issue`)
            ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='双色球'";
        $model = new Model(\lib\App::$config['db_lottery']);
        $model->exec($createTableSql);
        $model->table('double_lottery');
        //逐页获取数据
        for($p = 1; $p <= $totalPage; $p++) {
            $pageUrl = $p == 1 ? $url : str_replace('list.html', 'list_' . $p . '.html', $url);
            $result = $this->getDoubleLotteryTableData($pageUrl);
            foreach ($result as $item) {
                //已经存在的数据跳过
                if ($model->find($item['issue'])) {
                    continue;
                }
                if (!$model->add($item)) {
                    throw new \Exception('添加数据异常:' . json_encode($item));
                }
            }
        }
        return 0;
    }

    /**
     *解析双色球表格中的数据
     * @param $url
     * @return array|mixed
     * @throws \Exception
     */
    public function getDoubleLotteryTableData($url)
    {
        $result = $this->getUrlResult($url);
        preg_match_all('/<table.*?>(.*?)<\/table>/is', $result, $matches);
        if(!isset($matches[1][0])) {
            throw new \Exception('数据获取失败');
        }

        $trs = explode('</tr>', $matches[1][0]);
        $result = [];
        foreach($trs as $key => $item) {
            if($key < 2) continue;
            preg_match_all('/>([0-9\-]+)<\//', $item, $eleMathes);
            $data = $eleMathes[1];
            if(count($data) < 9) {
                continue;
            }
            //验证日期
            if(!strtotime($data[0])) {
                throw new \Exception('日期格式异常'.json_encode($data));
            }
            $fontBall = [];
            //前区号码验证
            for($i = 2; $i < 8; $i++) {
                $ball = $data[$i];
                if(!is_numeric($ball)) {
                    throw new \Exception('前区球号码不正确');
                }

                if(!$this->isRange($ball, 1, 33)) {
                    throw new \Exception('前区号码超出范围');
                }

                if(in_array($ball, $fontBall)) {
                    throw new \Exception('前区号码出现重复值');
                }

                $fontBall[] = $ball;
            }
            //后区号码验证
            if(!(is_numeric($data[8]) && $this->isRange($data[8], 1, 16))) {
                throw new \Exception('后区号码超出范围'.$data[8]);
            }

            $result[] = [
                'issue'=>$data[1],
                'front_1'=>$data[2],
                'front_2'=>$data[3],
                'front_3'=>$data[4],
                'front_4'=>$data[5],
                'front_5'=>$data[6],
                'front_6'=>$data[7],
                'back'=>$data[8],
                'date'=>$data[0],
            ];
        }
        if(!$result) {
            throw new \Exception('数据解析失败');
        }
        return $result;
    }


    /**
     * 获取大乐透数据
     * @param $url
     * @return array|mixed
     * @throws \Exception
     */
    public function getSuperLotteryTableData($url)
    {
        $result = $this->getUrlResult($url);
        //获取表内容
        preg_match_all('/<div\s*?class="result">.*?<tbody>(.*?)<\/tbody>.*?<\/div>/is', $result, $tbodyMatches);
        $trs = (array)explode('</tr>', $tbodyMatches[1][0]);
        if(!$trs) {
            throw new \Exception('获取结果中TR数据失败');
        }
        $result = [];
        //遍历TR数据
        foreach($trs as $item) {
            preg_match_all('/<td.*?>\s*([0-9,\-\.\s]+)\s*<\/td>/', $item, $itemMatches);
            //遇到不符合的跳过
            if(!$itemMatches[1]) {
                continue;
            }
            $data = $itemMatches[1];
            $fontBall = [];
            //前区五球判断
            for($i = 1; $i < 6; $i++) {
                $tmp = $data[$i];
                if(!$this->isRange($tmp , 1, 35)) {
                    throw new \Exception('前区球数值超出范围');
                }
                if(in_array($tmp, $fontBall)) {
                    throw new \Exception('前区球出现重复值异常');
                }
                $fontBall[] = $tmp;
            }
            //后区球判断
            if(!$this->isRange($data[6], 1, 12) || !$this->isRange($data[7], 1, 12)) {
                throw new \Exception('后区球数值超出范围'.$url);
            }
            if($data[6] == $data[7]) {
                throw new \Exception('后区球出现重复值异常'.$url);
            }
            //开奖日期判断
            if(!strtotime($data[18])) {
                throw new \Exception('日期格式异常'.json_encode($data));
            }
            $result[] = [
                "issue"=>$data[0],
                "red_1"=>$data[1],
                "red_2"=>$data[2],
                "red_3"=>$data[3],
                "red_4"=>$data[4],
                "red_5"=>$data[5],
                "blue_1"=>$data[6],
                "blue_2"=>$data[7],
                "first_num"=>(int)$data[8],
                "first_money"=>$data[9],
                "first_append_num"=>(int)$data[10],
                "first_append_money"=>$data[11],
                "second_num"=>(int)$data[12],
                "second_money"=>$data[13],
                "second_append_num"=>(int)$data[14],
                "second_append_money"=>$data[15],
                "sale_total"=>$data[16],
                "bonus_total"=>$data[17],
                "date"=>$data[18],
            ];
        }
        if(!$result) {
            throw new \Exception('数据解析失败');
        }
        return $result;
    }

    /**
     * 判断数值范围
     * @param $num
     * @param $min
     * @param $max
     * @return bool
     */
    public function isRange($num, $min, $max) {
        if(!is_numeric($num)) {
            return false;
        }
        return $num >= $min && $num <= $max ? true : false;
    }
}